ItIron2023
react
我們昨天看了最後一個關於實務上常碰到的issue,剩下的10天我們將進入react coding interview questions,多半是來自我實際面試時碰到的問題或是其觀念延伸,問題並不算太難,主要是針對jr等級的react developer,強烈建議各位在進入這個系列前可以先確保自己已經對過去20天我們探討的所有議題都有所了解,接下來會是一些綜合應用的部分,一樣都會透過一些類實務的情境測試你對React的了解,差別在於你現在多半不是要去解決某個bug,而是去達成一些商業需求或是根據程式碼回答指定的問題,準備好的話我們就開始吧! 不用擔心,今天的問題是個暖手的好機會!
請你觀察這個codesandbox以及下方的程式碼,在這份程式碼中我們塞了數個console.log,請回答在下列情況下,console中看到的log順序為何
import React, { useState, useEffect } from "react";
function App() {
const [count, setCount] = useState(0);
console.log("A");
useEffect(() => {
console.log("B");
return () => {
console.log("C");
};
}, []);
console.log("D");
useEffect(() => {
console.log("E");
});
useEffect(() => {
console.log("F");
}, [count]);
const increment = () => {
setCount(count + 1);
};
return (
<div>
<h1>Count: {count}</h1>
<button onClick={increment}>Increment</button>
</div>
);
}
1. 畫面第一次載入後
2. 點擊按鈕後
好了,作為練手這是個不錯的問題,當時這個題目來自在當時一家新創美商的面試,可以測試你對於react render邏輯的了解程度,首先要回答這個問題之前你需要先確認一件重要的事,這份程式碼是在什麼環境下執行的、是否有在StrictMode下,先確認這一點之後你才有辦法正確的回答這個問題。
我們在Day10曾經提過這個議題,React在StrictMode下為了協助你確認是否有意料外的side effect會執行你的hooks兩次,這會讓結果與我們預期的有些不同! 因此以下我們先以非StrictMode的前提下討論,我們先看一下第一次載入的情況。
第一次載入
首先我們知道useEffect會在render畫面後執行,所以一切與useEffect有關的都可以先當作沒看到,最先執行的會是
console.log("A");
console.log("D");
接著我們來處理useEffect的部分
useEffect(() => {
console.log("B");
return () => {
console.log("C");
};
}, []);
useEffect(() => {
console.log("E");
});
useEffect(() => {
console.log("F");
}, [count]);
分別來看三個useEffect吧,我們都知道useEffect在第一次render時都必定會執行,因此下方的程式碼會執行
console.log("B");
console.log("E");
console.log("F");
最終你在第一次render看到的會是
A
D
B
E
F
接著我們來處理比較容易有爭議的第二個情況
點擊按鈕後
同步的部分還是跟剛剛一樣,下方的程式碼仍會先執行
console.log("A");
console.log("D");
關鍵在於useEffect的處理,首先你應該知道下方這個不會執行,因為它有個空的dependency array,也就是只會在第一次渲染時執行callback,同時cleanup function僅會在組件unmount或是dependency array的值有更新才會執行,因此最終B & C都不會出現在結果中
useEffect(() => {
console.log("B");
return () => {
console.log("C");
};
}, []);
接著我們看一下另外兩個useEffect的dependency array,當沒有任何dependency array時表示每次re-render都會執行,而[count]表示count有更新時就會執行,所以下方兩個effect都會再次被執行
useEffect(() => {
console.log("E");
});
useEffect(() => {
console.log("F");
}, [count]);
最終你看到的結果是
A
D
E
F
今天我們利用這個面試題目複習了react render的一些邏輯,距離我被問這個問題已經有很長一段時間了,但我仍舊覺得這是個好問題,若你能完全答對表示你對於渲染的邏輯有著相當扎實的了解!搞清楚這些順序往往會讓你開發避免掉一些很微妙的問題,那麼我們明天見吧!
本文章同步發布於個人部落格,有興趣的朋友也可以來逛逛~!